Messaging is a method of communication between software components or applications. A messaging system is a peer-to-peer facility. A messaging client can send messages to, and receive messages from, any other clients. Each client typically connects to a messaging agent that provides facilities for creating, sending, receiving, and reading messages.
Messaging enables distributed communication that is loosely coupled. A component sends a message to a destination, and the recipient can retrieve the message from the destination. However, the sender and the receiver do not have to be available at the same time in order to communicate. In fact, the sender does not need to know anything about the receiver; nor does the receiver need to know anything about the sender. The sender and the receiver need to know only what message format and destination to use. In this respect, messaging differs from tightly coupled technologies, such as remote method invocation (RMI), which requires an application to know a remote application's method.
The Java message service (JMS) is a Java API that allows applications to create, send, receive, and read messages. Designed by Sun Microsystems and other partners, the JMS API defines a common set of interfaces and associated semantics that allow programs written in the Java programming language to communicate with other messaging implementations.
A typical JMS application may include a JMS provider, one or more JMS clients, messages, one or more administered objects, and one or more native clients. A JMS provider is a messaging system that implements the JMS interfaces and provides administrative and control features. JMS clients are the programs or components, written in the Java programming language, that produce and consume messages. Messages are the objects that communicate information between the JMS clients. Administered objects are preconfigured JMS objects created by an administrator for the use of clients. There are two kinds of administered objects: destinations and connection factories. Native clients are programs that use a messaging product's native client API instead of the JMS API. An application first created before the JMS API became available and subsequently modified is likely to include both JMS and native clients.
Typically, most current implementations of the JMS API provide support for both point-to-point (PTP) and the publish/subscribe (pub/sub) domains. A PTP product or application is built around the concept of message queues, senders, and receivers. Each message is addressed to a specific queue, and receiving clients extract messages from the queue(s) established to hold their messages. Queues retain all messages sent to them until the messages are consumed or until the messages expire. Under a PTP system, each message has only one consumer. A sender and a receiver of a message have no timing dependencies. The receiver can fetch the message whether or not it was running when the client sent the message. The receiver acknowledges the successful processing of a message. FIG. 1A is a block diagram illustrating an example of a PTP messaging configuration.
In a publish/subscribe (pub/sub) product or application, clients address messages to a topic. Publishers and subscribers are generally anonymous and may dynamically publish or subscribe to the content hierarchy. The system takes care of distributing the messages arriving from a topic's multiple publishers or its multiple subscribers. Topics retain messages only as long as it takes to distribute them to current subscribers. Under a pub/sub system, each message may have multiple consumers (also referred to as subscribers). Publishers and subscribers have a timing dependency. A client that subscribes to a topic can consume only messages published after the client has created a subscription, and the subscriber must continue to be active in order for the subscriber to consume messages. FIG. 1B is a block diagram illustrating an example of a pub/sub messaging configuration.
In addition, the JMS API relaxes this timing dependency to some extent by allowing clients to create durable subscriptions. Durable subscriptions can receive messages sent while the subscribers are not active. Durable subscriptions provide the flexibility and reliability of queues but still allow clients to send messages to many recipients. FIGS. 8A and 8B (described in greater detail below) are block diagrams illustrating examples of a durable subscription versus a non-durable subscription in an enterprise messaging system.
JMS messages may be consumed synchronously or asynchronously. Under the synchronous model, a subscriber or a receiver explicitly fetches the message from the destination by calling the “receive” method. The “receive” method can block until a message arrives or can time out if a message does not arrive within a specified time limit. Under the asynchronous model, a client can register a message listener with a consumer. A message listener is similar to an event listener. Whenever a message arrives at the destination, the JMS provider delivers the message by calling the listener's “on Message” method, which acts on the contents of the message.
FIG. 1C is a block diagram illustrating a typical object-oriented enterprise messaging system, such as a Java message system (JMS). Referring to FIG. 1C, two parts of a JMS application, destination and connection factories, are best maintained administratively rather than programmatically. These components are implemented as objects under object-oriented programming environments, particularly referred to as administered objects. The technology underlying these objects is likely to be very different from one implementation of the JMS API to another. Thus, the management of these objects varies from provider to provider.
JMS clients access these objects through interfaces that are portable, so a client application can run with little or no change on more than one implementation of the JMS API. Ordinarily, an administrator configures administered objects in a Java naming and directory interface (JNDI) API namespace, and JMS clients then look them up, using the JNDI API. For example, in a J2EE (Java 2 enterprise edition) development environment, an administrator may use a tool called j2eeadmin to perform the administrative tasks.
A connection factory is the object a client uses to create a connection with a message provider (e.g., a JMS provider). A connection factory may be created using the j2eeadmin tool for a PTP and/or a pub/sub domains. A connection factory encapsulates a set of connection configuration parameters that has been defined by an administrator.
A destination is the object a client uses to specify the target of messages it produces and the source of messages it consumes. In a PTP messaging domain, destinations are referred to as queues, while in a pub/sub domain, the destinations are referred to as topics. A JMS application may use multiple queues and topics.
A connection encapsulates a virtual connection with a JMS provider. A connection could represent an open TCP/IP socket between a client and a provider server's daemon. A connection may be used to create one or more sessions. When an application completes, any connections associated with the application have to be closed. Failure to close a connection can cause resources not to be released by the JMS provider. Closing a connection also closes its session and their message producers and message consumers. A session is a single-threaded context for producing and consuming messages. Sessions may be used to create message producers, message consumers, and messages.
A message producer is an object created by a session and is used for sending messages to a destination. A message consumer is an object created by a session and is used to receive messages sent to a destination. A message consumer allows a JMS client to register interest in a destination with a JMS provider. The JMS provider manages the delivery of messages from a destination to the registered consumers of the destination. Once a consumer is created, it becomes active and may be used to receive messages. A consumer may be closed via a “close” method. A message listener is an object that acts as an asynchronous event handler for messages. A message listener is not specific to a particular destination type. The same message listener may obtain messages from either a queue or a topic, depending on whether the listener is set for a queue receiver or a topic subscriber.
If a messaging application needs to filter the messages it receives, a JMS API message selector may be used to specify the messages a consumer is interested in. Message selectors assign the work of filtering messages to the JMS provider rather than to the application. A message selector is a string that contains an expression. The syntax of the expression is based on a subset of the conditional expression syntax according to a specification, such as SQL92 specification. The message consumer then receives only messages whose headers and properties match the selector. Typically, a message selector cannot select messages on the basis of the content of the message body.
The ultimate purpose of a JMS application is to produce and to consume messages that can then be used by other software applications. JMS messages have a basic format that is simple but highly flexible, allowing a user to create messages that match formats used by non-JMS applications on heterogeneous platforms. A typical JMS message includes a message header, one or more optional message properties, and an optional message body.
A JMS header typically contains a number of predefined fields that contain values that both clients and providers use to identify and to route messages. For example, every message has a unique identifier, a destination, and other fields, such as a timestamp and a priority level.
Message properties may used to set values in addition to those defined in the message header. For example, the message properties may be used to provide compatibility with other messaging systems, or alternatively, to create message selectors. There are several message body formats (also referred to as message types) defined by JMS API, which allow a user to send and to receive data in many different forms and provide compatibility with existing messaging formats.
As enterprise applications have become more popular and complicated, enterprise messaging systems have also become more complex. However, there has been a lack of improvement of the memory management and the efficiency of message delivery within an enterprise messaging system.